import { RedisModuleAsyncOptions } from '@nestjs-modules/ioredis';
import * as fs from 'fs';
import pino from 'pino';
import * as Joi from 'joi';
import { ConfigModule, ConfigModuleOptions, ConfigService } from '@nestjs/config';
import { TypeOrmModuleAsyncOptions, TypeOrmModuleOptions } from '@nestjs/typeorm';
import { Params } from 'nestjs-pino';
import { Entities } from '@/modules/entities';
import { JwtModuleOptions } from '@nestjs/jwt';
import { constant_Index_JwtConstants } from '../constants';

/**
 * @description Pino 日志配置。
 * @constant
 * @type {object}
 * @property {object} pinoHttp - Pino HTTP 配置对象。
 * @property {object} pinoHttp.stream - 日志流配置，使用文件写入流。
 * @property {object} pinoHttp.transport - 日志传输配置，根据环境变量 NODE_ENV 设置不同的传输目标。
 * @property {object} pinoHttp.serializers - 序列化器配置，用于自定义日志格式。
 */
export const Others_AppModulesConfig_Pina: Params = {
  pinoHttp: {
    stream: fs.createWriteStream('./log/my-logs.log', { flags: 'a' }),
    transport:
      process.env.NODE_ENV == 'development'
        ? {
            target: 'pino-pretty',
            options: {
              translateTime: 'SYS:standard',
              ignore: 'pid,hostname',
              colorize: true,
            },
          }
        : {
            target: 'pino-roll',
            options: {
              file: './log/log.txt',
              frequency: 'daily',
              mkdir: true,
            },
          },
    serializers: {
      err: pino.stdSerializers.err,
      req: (req) => req.method + '  ' + req.url,
      res: (res) => res.statusCode,
    },
  },
};

/**
 * @description Redis 模块配置。
 * @constant
 * @type {RedisModuleAsyncOptions}
 * @property {Function} useFactory - 配置工厂函数，返回 Redis 配置对象。
 */
export const Others_AppModulesConfig_Redis: RedisModuleAsyncOptions = {
  imports: [ConfigModule],
  inject: [ConfigService],
  useFactory: (configService: ConfigService) => {
    return {
      type: 'single',
      url: configService.get('REDIS_URL'),
      options: {
        password: configService.get('REDIS_PASSWORD'),
      },
    };
  },
};

const envFilePath = `appConfig/env/.env.${process.env.NODE_ENV || `development`}`;
/**
 * @description 配置模块的配置。
 * @constant
 * @type {object}
 * @property {string} envFilePath - 环境变量文件路径，根据环境变量 NODE_ENV 动态设置。
 * @property {boolean} isGlobal - 是否为全局配置模块。
 * @property {object} validationSchema - 配置验证模式，使用 Joi 定义。
 */
export const Others_AppModulesConfig_Config: ConfigModuleOptions = {
  envFilePath,
  isGlobal: true,
  validationSchema: Joi.object({
    NODE_ENV: Joi.string().valid('development', 'production', 'test').default('development'),
    DB_PORT: Joi.number().default(3306),
    DB_HOST: Joi.string(),
    DB_TYPE: Joi.string().valid('mysql', 'postgres'),
    DB_DATABASE: Joi.string().required(),
    DB_USERNAME: Joi.string().required(),
    DB_PASSWORD: Joi.string().required(),
    DB_SYNCHRONIZE: Joi.boolean().default(false),
  }),
};

/**
 * @description TypeORM 模块配置。
 * @constant
 * @type {object}
 * @property {Array} imports - 导入的模块列表，这里包括 ConfigModule。
 * @property {Array} inject - 注入的依赖列表，这里包括 ConfigService。
 * @property {Function} useFactory - 配置工厂函数，返回 TypeORM 配置对象。
 */
export const Others_AppModulesConfig_TypeOrm: TypeOrmModuleAsyncOptions = {
  imports: [ConfigModule],
  inject: [ConfigService],
  useFactory: (configService: ConfigService) => {
    return {
      type: 'mysql',
      host: configService.get('DB_HOST'),
      port: configService.get('DB_PORT'),
      username: configService.get('DB_USERNAME'),
      password: configService.get('DB_PASSWORD'),
      database: configService.get('DB_DATABASE'),
      // logging: ['query', 'error'],
      logging: ['error'],
      entities: Entities,
      synchronize: true,
      extra: {
        supportBigNumbers: false, // 启用对大数字的支持
      },
    } as TypeOrmModuleOptions;
  },
};
/**
 * @description JWT 模块配置。
 * @constant
 * @property {boolean} global - 设置为 true，表示此 JWT 模块将在整个应用程序中全局可用。
 * @property {string} secret - JWT 签名使用的密钥。
 * @property {object} signOptions - JWT 签名的选项，这里设置了过期时间为 36000000 秒。
 */
export const Others_AppModulesConfig_JwtModule: JwtModuleOptions = {
  global: true,
  secret: constant_Index_JwtConstants.secret,
  signOptions: { expiresIn: '36000000s' },
};
